package cn.dapeng.base;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.CountDownLatch;

/**
 * 验证：
 * 1. 单线程和多线程的效率
 * 2. 线程数量对效率的影响
 *
 * @author spikeCong
 * @date 2022/10/14
 */
public class SingleOrMultiThread {

    public static final int length = 100000000;

    public static double[] data = new double[length];

    static {
        for (int i = 0; i < length; i++) {
            data[i] = Math.random();
        }
    }


    public static void m1() {
        long begin = System.currentTimeMillis();
        double sum = 0;
        for (int i = 0; i < length; i++) {
            sum += data[i];
        }

        long end = System.currentTimeMillis();
        System.out.println("sum = " + print(sum) + " \t time = " + (end - begin));
    }


    public static void m2() throws Exception {
        long begin = System.currentTimeMillis();
        final double[] sum = new double[2];

        Thread thread1 = new Thread(() -> {
            double a = 0;
            for (int i = 0; i < length / 2; i++) {
                a += data[i];
            }
            sum[0] = a;
        });

        Thread thread2 = new Thread(() -> {
            double b = 0;
            for (int i = length / 2; i < length; i++) {
                b += data[i];
            }
            sum[1] = b;
        });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();

        long end = System.currentTimeMillis();
        System.out.println("sum = " + print(sum[0] + sum[1]) + " \t time = " + (end - begin));
    }

    public static void m3() throws Exception {
        long begin = System.currentTimeMillis();

        int segment = Runtime.getRuntime().availableProcessors();
        CountDownLatch countDownLatch = new CountDownLatch(segment);

        final double[] sum = new double[segment];

        for (int i = 0; i < segment; i++) {
            final int index = i;
            Thread thread = new Thread(() -> {
                double a = 0;
                for (int j = (length / segment) * index; j < (length / segment) * (index + 1); j++) {
                    a += data[j];
                }
                sum[index] = a;
                countDownLatch.countDown();
            });
            thread.start();
        }

        countDownLatch.await();
        double s = 0;
        for (int i = 0; i < segment; i++) {
            s += sum[i];
        }
        long end = System.currentTimeMillis();
        System.out.println("sum = " + print(s) + " \t time = " + (end - begin));
    }


    public static void main(String[] args) throws Exception {
        m1();
        m2();
        m3();
    }


    public static String print(double d) {
        BigDecimal v = BigDecimal.valueOf(d);
        return v.setScale(2, RoundingMode.HALF_UP).toString();
    }
}
